package com.golf.client.ui;

import com.golf.client.course.renderer.CompositeRenderer;
import com.golf.server.engine.phys.Engine;

/**
 * The main loop of the client that is responsible for updating state,
 * and ensuring that the canvas is correctly re-drawn.
 * 
 * @author gfloodgate
 */
public class MainLoop implements Runnable
{

	/** The allowed frame duration for the given FPS (25). */
	private static final long FRAME_ALLOWED_DURATION = 1000L / 25L;

	
	/** A flag indicating if the thread is running. */
	private volatile boolean isRunning = true;
	
	/** The time that a frame was last synchronised on. */
	private long lastFrameSyncTime;
	
	
	/** The renderer that is responsible for drawing the game state. */
	private final CompositeRenderer renderer;
	
	private final Engine e;
	
	
	/**
	 * Create an instance of the main loop.
	 * 
	 * @param renderer The renderer that will be drawing the game state.
	 */
	public MainLoop(final Engine e, final CompositeRenderer renderer)
	{
	    this.e = e;
		this.renderer = renderer;
	}
	
	
	/**
	 * {@inheritDoc}
	 */
	public void run() 
	{
		// Set the first frame sync time.
		lastFrameSyncTime = System.currentTimeMillis();
	
// ??		CommsChannel channel;
		while (isRunning)
		{
			//update state
		    if (e.isFinished())
		    {
		        System.out.println("Engine thinks everything is resting.");
		        e.reset();
		    }
		    
			// Update the rendered state, based on any state change.
			renderer.update();
			
			// Synchronize with the frame rate (waiting if required).
			waitForFrameSync();
		}
	}
	

	/**
	 * A method that tries to wait until the next frame sync is required.
	 * <p>
	 * NB: This is naively simple, if a frame take too long to render, there
	 * is no concept of frame skipping, or re-synchronization. 
	 * </p>
	 */
	private void waitForFrameSync() 
	{
		// Mark a new sync time, and work out (if any) time that must be waited for.
		lastFrameSyncTime = lastFrameSyncTime + FRAME_ALLOWED_DURATION;
		long timeLeft = lastFrameSyncTime - System.currentTimeMillis();
		
		//System.out.println("Timeleft is: " + String.valueOf(timeLeft));
		
		try
		{
			// Sleep if there is any required wait time.
			Thread.sleep(Math.max(0, timeLeft));
		}
		catch (InterruptedException ie)
		{
			ie.printStackTrace();
		}
	}

}
